import hashlib
from datetime import timezone, datetime, timedelta
from typing import Annotated

import jwt
from fastapi import APIRouter, Depends, HTTPException, status, Form
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from sqlalchemy.orm import Session

from ..config.config import config
from ..sqllite.database import sessionlocal
from ..model import User
from ..schames import UserCreate, UserALL

auth = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/auth/login")


# 获取数据库
def get_db():
    try:
        db = sessionlocal()
        yield db
    finally:
        db.close()


# 使用jwt格式的token
# 创建jwt
def create_token(data: dict):
    if not data:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Invalid user")
    to_encode = data.copy()
    to_encode.update({"exp": datetime.now(timezone.utc) + timedelta(minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES)})
    token = jwt.encode(to_encode, config.SECRET_KEY, algorithm=config.ALGORITHM)
    return token

# 刷新token的函数
def refresh_token(data: dict):
    if not data:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Invalid user")
    to_encode = data.copy()
    to_encode.update({"exp": datetime.now(timezone.utc) + timedelta(minutes=config.REFRESH_TOKEN_EXPIRE_MINUTES)})
    token = jwt.encode(to_encode, config.SECRET_KEY, algorithm=config.ALGORITHM)
    return token


def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
    if not token:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")
    try:
        payload = jwt.decode(token, config.SECRET_KEY, algorithms=[config.ALGORITHM])
        user = db.query(User).filter(User.id == payload.get("user_id")).first()
        return user
    except jwt.ExpiredSignatureError:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token expired")


def get_current_active_user(user: UserALL = Depends(get_current_user)):
    if not user:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")
    elif not user.is_active:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Inactive user")
    return user


# 校验用户
def authenticate_user(name: str, password: str, db: Session):
    if not name or not password:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid user")
    try:
        user = db.query(User).filter(User.name == name).first()
        if not user:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid user")
        password_hash = hashlib.sha256(password.encode()).hexdigest()
        if password_hash != user.password_hash:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid password")
        else:
            return user
    except Exception as e:
        return None


@auth.post("/login")
async def login(form_user: Annotated[OAuth2PasswordRequestForm, Depends()], db: Session = Depends(get_db)):
    if not form_user.username:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid user")
    try:
        user = authenticate_user(form_user.username, form_user.password, db)
        if not user:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid user")
    except Exception as e:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid user")
    token = create_token({"user_id": user.id})
    return {"access_token": token, "token_type": "bearer"}


@auth.post("/register")
async def register(formdata: UserCreate = Form(...), db: Session = Depends(get_db)):
    if not formdata:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid user")
    try:
        user = db.query(User).filter(User.name == formdata.name).first()
        if user:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="用户已存在")
    except Exception as e:
        print(e)
        return {"message": "用户已存在"}
    password_hash = hashlib.sha256(formdata.password.encode()).hexdigest()
    user_create = User(name=formdata.name, nick_name=formdata.nick_name, password_hash=password_hash)
    try:
        db.add(user_create)
        db.commit()
        db.refresh(user_create)
    except Exception as e:
        return {"message": "用户注册失败"}
    return {"code": 200, "message": "User registered successfully", }




@auth.post("/refresh_token")  # 用户刷新token，即延长登录时间
async def refresh_token(current_user = Depends(get_current_active_user), db: Session = Depends(get_db)):
    try:
        if not current_user:
            raise HTTPException(statsu_code = status.HTTP_401_UNAUTHORIZED, detail = "刷新token失败,未授权")
        token = create_token({"user_id": current_user.id})
        return {"access_token": token, "token_type": "bearer"}
    except Exception as e:
        raise HTTPException(status_code = status.HTTP_401_UNAUTHORIZED, detail = "刷新token失败")
